package app_kvServer;

import infrastructure.KVMessageImp;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Observer;

import common.messages.KVMessage;
import common.messages.KVMessage.StatusType;

import serverCommunication.CommunicationListener;
import serverCommunication.IResponse;
import serverCommunication.Server;


public class KVServer implements CommunicationListener {
	
	private Server server;
	
	Map<String, String> keyValueStorage;
	
	
	/**
	 * Start KV Server at given port
	 * @param port given port for storage server to operate
	 */
	public KVServer(int port) {
		this.keyValueStorage = new HashMap<String, String>();
		server = new Server(port, this);
		server.start();
		System.out.println("Running ...");
	}
	
	/**
     * Main entry point for the echo server application. 
     * @param args contains the port number at args[0].
     */
    public static void main(String[] args) {
    	try {
			if(args.length != 1) {
				System.out.println("Error! Invalid number of arguments!");
				System.out.println("Usage: Server <port>!");
			} else {
				int port = Integer.parseInt(args[0]);
				new KVServer(port);
			}
		} catch (NumberFormatException nfe) {
			System.out.println("Error! Invalid argument <port>! Not a number!");
			System.out.println("Usage: Server <port>!");
			System.exit(1);
		}
    }

	@Override
	public void notifyMessage(String message, IResponse response) {
		// TODO Process message
		String [] tokens = message.split(" ");
		KVMessage result = null;
		String replyMessage = "";
		try {
			result = handleMessage(tokens);
		} catch (Exception e1) {
			replyMessage = "ERROR: " + e1.getMessage();
		}
		
		if (result != null) {
			response.sendResponse(result);
		} else {
			response.sendMessage(replyMessage);
		}		
	}

	private synchronized KVMessage handleMessage(String[] tokens) throws Exception {
		KVMessage result = null; 
		String key, value = null;
		StatusType status;
		if (tokens[0].toUpperCase().equals(Commands.GET.toString())) {
			key = tokens[1];
			status = StatusType.GET;			
			if ( this.keyValueStorage.containsKey(key)) {
				status = StatusType.GET_SUCCESS;
				value = this.keyValueStorage.get(key);
			}
			else {
				status = StatusType.GET_ERROR;
				value = "";
			}
			
			result = new KVMessageImp(value, key, status);
		} else if (tokens[0].toUpperCase().equals(Commands.PUT.toString())) {
			key = tokens[1];
			status = StatusType.PUT;
			if (tokens.length > 2)
				value = tokens[2].trim();
			if (value == null || value.equals("") || value.equals("null")) {
				status = StatusType.DELETE_ERROR;
				if (this.keyValueStorage.containsKey(key)){
					this.keyValueStorage.remove(key);
					status = StatusType.DELETE_SUCCESS;
				}
			}
			else {
				if (this.keyValueStorage.containsKey(key)){
					status = StatusType.PUT_UPDATE;	
					
				} else {
					status = StatusType.PUT_SUCCESS;	
				}
				
				this.keyValueStorage.put(key, value);
			}
			
			result = new KVMessageImp(value, key, status);
		}
		
		return result;
	}
	
}
